home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libc / dos / process / dosexec.c next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  11.5 KB  |  526 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <libc/stubs.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>
  9. #include <process.h>
  10. #include <go32.h>
  11. #include <dpmi.h>
  12. #include <ctype.h>
  13. #include <libc/dosexec.h>
  14. #include <libc/unconst.h>
  15. #include <libc/dosio.h>
  16.  
  17. extern char **environ;
  18.  
  19. int __dosexec_in_system = 0;
  20.  
  21. typedef struct {
  22.   unsigned short eseg;
  23.   unsigned short argoff;
  24.   unsigned short argseg;
  25.   unsigned short fcb1_off;
  26.   unsigned short fcb1_seg;
  27.   unsigned short fcb2_off;
  28.   unsigned short fcb2_seg;
  29. } Execp;
  30.  
  31. static Execp parm;
  32.  
  33. static unsigned long tbuf;
  34.  
  35. static unsigned long talloc(size_t amt)
  36. {
  37.   unsigned long rv = tbuf;
  38.   tbuf += amt;
  39.   return rv;
  40. }
  41.  
  42. static int direct_exec_tail(const char *program, const char *args, char * const envp[])
  43. {
  44.   __dpmi_regs r;
  45.   unsigned long program_la;
  46.   unsigned long arg_la;
  47.   unsigned long parm_la;
  48.   unsigned long env_la, env_e_la;
  49.   char arg_header[3];
  50.   char short_name[FILENAME_MAX];
  51.   const char *progname;
  52.   unsigned proglen;
  53.   int i;
  54.   
  55.   sync();
  56.  
  57.   proglen = strlen(program)+1;
  58.   if(_USE_LFN) {
  59.     dosmemput(program, proglen, tbuf);
  60.     r.x.ax = 0x7160;            /* Truename */
  61.     r.x.cx = 1;                /* Get short name */
  62.     r.x.ds = r.x.es = tbuf / 16;
  63.     r.x.si = r.x.di = tbuf & 15;
  64.     __dpmi_int(0x21, &r);
  65.     if (r.x.flags & 1)
  66.     {
  67.       errno = __doserr_to_errno(r.x.ax);
  68.       return -1;
  69.     }
  70.     dosmemget(tbuf, FILENAME_MAX, short_name);
  71.     progname = short_name;
  72.     proglen = strlen(short_name)+1;
  73.   } else
  74.     progname = program;
  75.   
  76.   program_la = talloc(proglen);
  77.   arg_la = talloc(strlen(args)+3);
  78.   parm_la = talloc(sizeof(Execp));
  79.  
  80.   dosmemput(progname, proglen, program_la);
  81.   
  82.   arg_header[0] = strlen(args);
  83.   arg_header[1] = '\r';
  84.   dosmemput(arg_header, 1, arg_la);
  85.   dosmemput(args, strlen(args), arg_la+1);
  86.   dosmemput(arg_header+1, 1, arg_la+1+strlen(args));
  87.  
  88.   do {
  89.     env_la = talloc(1);
  90.   } while (env_la & 15);
  91.   talloc(-1);
  92.   for (i=0; envp[i]; i++)
  93.   {
  94.     env_e_la = talloc(strlen(envp[i])+1);
  95.     dosmemput(envp[i], strlen(envp[i])+1, env_e_la);
  96.   }
  97.   arg_header[0] = 0;
  98.   arg_header[1] = 1;
  99.   arg_header[2] = 0;
  100.   dosmemput(arg_header, 3, talloc(3));
  101.   env_e_la = talloc(proglen);
  102.   dosmemput(progname, proglen, env_e_la);
  103.  
  104.   parm.eseg = env_la / 16;
  105.   parm.argseg = arg_la / 16;
  106.   parm.argoff = arg_la & 15;
  107.   dosmemput(&parm, sizeof(parm), parm_la);
  108.  
  109.   r.x.ax = 0x4b00;
  110.   r.x.ds = program_la / 16;
  111.   r.x.dx = program_la & 15;
  112.   r.x.es = parm_la / 16;
  113.   r.x.bx = parm_la & 15;
  114.   __dpmi_int(0x21, &r);
  115.   if (r.x.flags & 1)
  116.   {
  117.     errno = __doserr_to_errno(r.x.ax);
  118.     return -1;
  119.   }
  120.   
  121.   r.h.ah = 0x4d;
  122.   __dpmi_int(0x21, &r);
  123.   
  124.   if (r.x.flags & 1)
  125.   {
  126.     errno = __doserr_to_errno(r.x.ax);
  127.     return -1;
  128.   }
  129.   return r.x.ax;
  130. }
  131.  
  132. int
  133. _dos_exec(const char *program, const char *args, char * const envp[])
  134. {
  135.   tbuf = __tb;
  136.   return direct_exec_tail(program, args, envp);
  137. }
  138.  
  139. static char GO32_STRING[] = "go32.exe";
  140.  
  141. static int direct_exec(const char *program, char **argv, char **envp)
  142. {
  143.   int i, arglen;
  144.   char *args, *argp;
  145.  
  146.   tbuf = __tb;
  147.  
  148.   arglen = 0;
  149.   for (i=1; argv[i]; i++)
  150.     arglen += strlen(argv[i]) + 1;
  151.   args = (char *)alloca(arglen+1);
  152.   argp = args;
  153.   for (i=1; argv[i]; i++)
  154.   {
  155.     const char *p = argv[i];
  156.     if (argp - args > 125)
  157.       break;
  158.     *argp++ = ' ';
  159.     while (*p)
  160.     {
  161.       if (argp - args > 125)
  162.         break;
  163.       *argp++ = *p++;
  164.     }
  165.   }
  166.   *argp = 0;
  167.   
  168.   return direct_exec_tail(program, args, envp);
  169. }
  170.  
  171. typedef struct {
  172.   char magic[16];
  173.   int struct_length;
  174.   char go32[16];
  175. } StubInfo;
  176. #define STUB_INFO_MAGIC "StubInfoMagic!!"
  177.  
  178. static int go32_exec(const char *program, char **argv, char **envp)
  179. {
  180.   char *save_argv0;
  181.   int is_stubbed = 0;
  182.   int found_si = 0;
  183.   StubInfo si;
  184.   unsigned short header[3];
  185.   int pf, i;
  186.   char *go32, *sip=0;
  187.   char rpath[80];
  188.   int stub_offset, argc;
  189.  
  190.   int v2_0 = 0;
  191.   int si_la=0, rm_la, rm_seg;
  192.   short *rm_argv;
  193.   char cmdline[34];
  194.  
  195.   if (__dosexec_in_system)
  196.     return direct_exec(program, argv, envp);
  197.  
  198.   pf = open(program, O_RDONLY|O_BINARY);
  199.  
  200.   read(pf, header, sizeof(header));
  201.   if (header[0] == 0x010b || header[0] == 0x014c)
  202.   {
  203.     is_stubbed = 1;
  204.   }
  205.   else if (header[0] == 0x5a4d)
  206.   {
  207.     int header_offset = (long)header[2]*512L;
  208.     if (header[1])
  209.       header_offset += (long)header[1] - 512L;
  210.     lseek(pf, 512, 0);
  211.     read(pf, cmdline, 8);
  212.     cmdline[8] = 0;
  213.     if (strcmp(cmdline, "go32stub") == 0)
  214.       v2_0 = 1;
  215.     else
  216.     {
  217.       lseek(pf, header_offset - 4, 0);
  218.       read(pf, &stub_offset, 4);
  219.       header[0] = 0;
  220.       read(pf, header, sizeof(header));
  221.       if (header[0] == 0x010b)
  222.     is_stubbed = 1;
  223.       if (header[0] == 0x014c)
  224.     is_stubbed = 1;
  225.       lseek(pf, stub_offset, 0);
  226.       read(pf, &si, sizeof(si));
  227.       if (memcmp(STUB_INFO_MAGIC, si.magic, 16) == 0)
  228.     found_si = 1;
  229.     }
  230.   }
  231.   if (!is_stubbed && !v2_0)
  232.   {
  233.     close(pf);
  234.     return direct_exec(program, argv, envp);
  235.   }
  236.  
  237.   if (found_si)
  238.     go32 = si.go32;
  239.   else
  240.     go32 = GO32_STRING;
  241.  
  242.   if (v2_0)
  243.   {
  244.     strcpy(rpath, program);
  245.   }
  246.   else
  247.   {
  248.     if (!__dosexec_find_on_path(go32, envp, rpath))
  249.     {
  250.       close(pf);
  251.       return direct_exec(program, argv, envp); /* give up and just run it */
  252.     }
  253.  
  254.     if (found_si)
  255.     {  
  256.       lseek(pf, stub_offset, 0);
  257.       sip = (char *)alloca(si.struct_length);
  258.       read(pf, sip, si.struct_length);
  259.     }
  260.   }
  261.   close(pf);
  262.  
  263.   save_argv0 = argv[0];
  264.   argv[0] = unconst(program, char *); /* since that's where we really found it */
  265.  
  266.   tbuf = __tb;
  267.  
  268.   if (found_si)
  269.   {
  270.     si_la = talloc(si.struct_length);
  271.     dosmemput(sip, si.struct_length, si_la);
  272.   }
  273.   
  274.   for (argc=0; argv[argc]; argc++);
  275.   rm_la = talloc(2*(argc+1));
  276.   rm_seg = (__tb >> 4) & 0xffff;
  277.   rm_argv = (short *)alloca((argc+1) * sizeof(short));
  278.   for (i=0; i<argc; i++)
  279.   {
  280.     int sl = strlen(argv[i]) + 1;
  281.     int q = talloc(sl);
  282.     dosmemput(argv[i], sl, q);
  283.     rm_argv[i] = (q - (rm_seg<<4)) & 0xffff;
  284.   }
  285.   rm_argv[i] = 0;
  286.   dosmemput(rm_argv, 2*(argc+1), rm_la);
  287.   
  288.   sprintf(cmdline, " !proxy %04x %04x %04x %04x %04x",
  289.     argc, rm_seg, (rm_la - (rm_seg<<4))&0xffff,
  290.     rm_seg, (si_la - (rm_seg<<4))&0xffff);
  291.   if (!found_si)
  292.     cmdline[22] = 0; /* remove stub information */
  293.  
  294.   argv[0] = save_argv0;
  295.  
  296.   return direct_exec_tail(rpath, cmdline, envp);
  297. }
  298.  
  299. int
  300. __dosexec_command_exec(const char *program, char **argv, char **envp)
  301. {
  302.   const char *comspec=0;
  303.   char *cmdline;
  304.   char *newargs[3];
  305.   int cmdlen;
  306.   int i;
  307.   
  308.   cmdlen = strlen(program) + 4;
  309.   for (i=0; argv[i]; i++)
  310.     cmdlen += strlen(argv[i]) + 1;
  311.   cmdline = (char *)alloca(cmdlen);
  312.   
  313.   strcpy(cmdline, "/c ");
  314.   for (i=0; program[i] > ' '; i++)
  315.   {
  316.     if (program[i] == '/')
  317.       cmdline[i+3] = '\\';
  318.     else
  319.       cmdline[i+3] = program[i];
  320.   }
  321.   for (; program[i]; i++)
  322.     cmdline[i+3] = program[i];
  323.   cmdline[i+3] = 0;
  324.   for (i=1; argv[i]; i++)
  325.   {
  326.     strcat(cmdline, " ");
  327.     strcat(cmdline, argv[i]);
  328.   }
  329.   for (i=0; envp[i]; i++)
  330.     if (strncmp(envp[i], "COMSPEC=", 8) == 0)
  331.       comspec = envp[i]+8;
  332.   if (!comspec)
  333.     for (i=0; environ[i]; i++)
  334.       if (strncmp(environ[i], "COMSPEC=", 8) == 0)
  335.         comspec = environ[i]+8;
  336.   if (!comspec)
  337.     comspec = "c:\\command.com";
  338.   newargs[0] = unconst(comspec, char *);
  339.   newargs[1] = cmdline;
  340.   newargs[2] = 0;
  341.   i = direct_exec(comspec, newargs, envp);
  342.   return i;
  343. }
  344.  
  345. static int script_exec(const char *program, char **argv, char **envp)
  346. {
  347.   char line[130], interp[80], iargs[130];
  348.   FILE *f;
  349.   char **newargs;
  350.   int i, hasargs=0;
  351.  
  352.   f = fopen(program, "rt");
  353.   if (!f)
  354.   {
  355.     errno = ENOENT;
  356.     return -1;
  357.   }
  358.   fgets(line, 130, f);
  359.   fclose(f);
  360.   iargs[0] = 0;
  361.   interp[0] = 0;
  362.   sscanf(line, "#! %s %[^\n]", interp, iargs);
  363.   if (interp[0] == 0)
  364.     return __dosexec_command_exec(program, argv, envp); /* it couldn't be .exe or .com if here */
  365.   if (iargs[0])
  366.     hasargs=1;
  367.  
  368.   for (i=0; argv[i]; i++);
  369.   newargs = (char **)alloca((i+2+hasargs)*sizeof(char *));
  370.   for (i=0; argv[i]; i++)
  371.     newargs[i+1+hasargs] = unconst(argv[i], char *);
  372.   newargs[i+1+hasargs] = 0;
  373.   newargs[0] = unconst(argv[0], char *); /* it might work right, if not in system() */
  374.   if (hasargs)
  375.     newargs[1] = iargs;
  376.  
  377.   i = spawnvpe(P_WAIT, interp, newargs, envp);
  378.   return i;
  379. }
  380.  
  381. static struct {
  382.   const char *extension;
  383.   int (*interp)(const char *, char **, char **);
  384. } interpreters[] = {
  385.   { ".com", direct_exec },
  386.   { ".exe", go32_exec },
  387.   { ".bat", __dosexec_command_exec },
  388.   { "",     go32_exec },
  389.   { 0,      script_exec },
  390.   { 0,      0 },
  391. };
  392. #define INTERP_NO_EXT 3
  393.  
  394. /*-------------------------------------------------*/
  395.  
  396. char *
  397. __dosexec_find_on_path(const char *program, char *envp[], char *buf)
  398. {
  399.   char *pp, *rp, *pe;
  400.   const char *ptr;
  401.   int i, hasdot=0, haspath=0;
  402.   int tried_dot = 0;
  403.  
  404.   strcpy(buf, program);
  405.   rp = buf + strlen(buf);
  406.  
  407.   for (ptr=program; *ptr; ptr++)
  408.   {
  409.     if (*ptr == '.')
  410.       hasdot = 1;
  411.     if (*ptr == '/' || *ptr == '\\' || *ptr == ':')
  412.     {
  413.       haspath = 1;
  414.       hasdot = 0;
  415.     }
  416.   }
  417.  
  418.   if (hasdot)
  419.   {
  420.     if (access(buf, 0) == 0 && access(buf, D_OK))
  421.       return buf;
  422.   }
  423.   else
  424.     for (i=0; interpreters[i].extension; i++)
  425.     {
  426.       strcpy(rp, interpreters[i].extension);
  427.       if (access(buf, 0) == 0 && access(buf, D_OK))
  428.     return buf;
  429.     }
  430.  
  431.   if (haspath)
  432.     return 0;
  433.   *rp = 0;
  434.  
  435.   pp = 0;
  436.   for (i=0; envp[i]; i++)
  437.     if (strncmp(envp[i], "PATH=", 5) == 0)
  438.       pp = envp[i] + 5;
  439.   if (pp == 0)
  440.     return 0;
  441.  
  442.   while (1)
  443.   {
  444.     if (!tried_dot)
  445.     {
  446.       rp = buf;
  447.       pe = pp;
  448.       tried_dot = 1;
  449.     }
  450.     else
  451.     {
  452.       rp = buf;
  453.       for (pe = pp; *pe && *pe != ';'; pe++)
  454.         *rp++ = *pe;
  455.       pp = pe+1;
  456.       if (rp > buf && rp[-1] != '/' && rp[-1] != '\\' && rp[-1] != ':')
  457.         *rp++ = '/';
  458.     }
  459.     for (ptr = program; *ptr; ptr++)
  460.       *rp++ = *ptr;
  461.     *rp = 0;
  462.     
  463.     if (hasdot)
  464.     {
  465.       if (access(buf, 0) == 0 && access(buf, D_OK))
  466.     return buf;
  467.     }
  468.     else
  469.     {
  470.       for (i=0; interpreters[i].extension; i++)
  471.       {
  472.         strcpy(rp, interpreters[i].extension);
  473.         if (access(buf, 0) == 0 && access(buf, D_OK))
  474.           return buf;
  475.       }
  476.     }
  477.     if (*pe == 0)
  478.       return 0;
  479.   }
  480. }
  481.  
  482. int __spawnve(int mode, const char *path, char *const argv[], char *const envp[])
  483. {
  484.   /* This is the one that does the work! */
  485.   union { char *const *x; char **p; } u;
  486.   int i = -1;
  487.   char **argvp;
  488.   char **envpp;
  489.   char rpath[80], *rp, *rd=0;
  490.  
  491.   u.x = argv; argvp = u.p;
  492.   u.x = envp; envpp = u.p;
  493.  
  494.   fflush(stdout); /* just in case */
  495.   for (rp=rpath; *path; *rp++ = *path++)
  496.   {
  497.     if (*path == '.')
  498.       rd = rp;
  499.     if (*path == '\\' || *path == '/')
  500.       rd = 0;
  501.   }
  502.   *rp = 0;
  503.   if (rd)
  504.   {
  505.     for (i=0; interpreters[i].extension; i++)
  506.       if (stricmp(rd, interpreters[i].extension) == 0)
  507.         break;
  508.   }
  509.   while (access(rpath, 0) && access(rpath, D_OK))
  510.   {
  511.     i++;
  512.     if (interpreters[i].extension == 0 || rd)
  513.     {
  514.       errno = ENOENT;
  515.       return -1;
  516.     }
  517.     strcpy(rp, interpreters[i].extension);
  518.   }
  519.   if (i == -1)
  520.     i = INTERP_NO_EXT;
  521.   i = interpreters[i].interp(rpath, argvp, envpp);
  522.   if (mode == P_OVERLAY)
  523.     exit(i);
  524.   return i;
  525. }
  526.